import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_t/base/error_river_widget.dart';
import 'package:riverpod_t/base/loading_widget.dart';

/// 适用于整个 Widget 需要访问 Provider 的情况 如:列表之类

class BaseConsumerWidget<S> extends ConsumerWidget {
  final ProviderListenable<AsyncValue<S>> provider;
  final Widget Function(BuildContext context, S state, WidgetRef ref) builder;
  final bool skipLoadingOnRefresh;
  final bool skipLoadingOnReload;
  final Widget Function(Object error, StackTrace stackTrace)? errorBuilder;
  final VoidCallback? refresh;
  final Widget Function()? loadingBuilder;

  /// 监听回调方法
  final Function(BuildContext context, AsyncValue<S>, AsyncValue<S>)? listenStateChange;

  const BaseConsumerWidget({
    super.key,
    required this.provider,
    required this.builder,
    this.skipLoadingOnRefresh = true,
    this.skipLoadingOnReload = false,
    this.errorBuilder,
    this.loadingBuilder,
    this.refresh,
    this.listenStateChange,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.listen(provider, (p, n) => _listenStateChange(context, p, n));
    // ref.invalidate(provider);
    return ref
        .watch(provider)
        .when(
          skipLoadingOnRefresh: skipLoadingOnRefresh,
          skipLoadingOnReload: skipLoadingOnRefresh,
          data: (state) => builder(context, state, ref),
          error:
              (error, stack) =>
                  errorBuilder?.call(error, stack) ?? _defaultErrorBuilder(error, stack),
          loading: () => loadingBuilder?.call() ?? _loadingBuilder(),
        );
  }

  /// 监听回调
  void _listenStateChange(BuildContext context, previous, next) {
    if (listenStateChange != null) listenStateChange!(context, previous, next);
  }

  /// 出错页面
  Widget _defaultErrorBuilder(Object error, StackTrace stack) {
    return ErrorRiverWidget(type: ErrorPageType.page, refreshMethod: () => refresh?.call());
  }

  /// loading 页面
  Widget _loadingBuilder() {
    return LoadingWidget();
  }
}
